import os
import PyPDF2
import uuid
import time
import re
import subprocess
import json
from gtts import gTTS
from nltk.tokenize import word_tokenize

# 默认每个音频段的最大长度 (100秒)
MAX_WORDS_PER_SEGMENT = 150  # 根据经验，大约100秒的音频

def clean_text(text):
    """清理文本，删除特殊字符和多余空格"""
    cleaned = re.sub(r'[^\w\s\.,;:\-\'"]', ' ', text)  # 只保留基本字符
    cleaned = re.sub(r'\s+', ' ', cleaned).strip()  # 合并多个空格
    return cleaned

def text_to_segments(text, max_words_per_segment=MAX_WORDS_PER_SEGMENT):
    """
    将文本分割成适合处理的段落
    
    Args:
        text: 需要分割的文本
        max_words_per_segment: 每段最大单词数
    
    Returns:
        list: 文本段落列表
    """
    # 清理文本
    text = clean_text(text)
    
    # 分词
    words = word_tokenize(text)
    
    # 分段
    segments = []
    for i in range(0, len(words), max_words_per_segment):
        segment = ' '.join(words[i:i+max_words_per_segment])
        segments.append(segment)
    
    return segments, words

def get_segment_name(first_word, last_word):
    """
    基于首词和尾词创建文件名
    """
    # 确保文件名安全
    first_word = re.sub(r'[^\w]', '', first_word.lower())
    last_word = re.sub(r'[^\w]', '', last_word.lower())
    
    # 如果单词为空，使用UUID
    if not first_word:
        first_word = f"seg{uuid.uuid4().hex[:6]}"
    if not last_word:
        last_word = f"seg{uuid.uuid4().hex[:6]}"
        
    return f"{first_word}-{last_word}"

def get_file_duration(file_path):
    """
    使用ffprobe获取音频文件时长（秒）
    返回浮点数
    """
    try:
        # 使用ffprobe获取音频时长
        cmd = [
            'ffprobe', 
            '-v', 'error', 
            '-show_entries', 'format=duration', 
            '-of', 'json', 
            file_path
        ]
        
        result = subprocess.run(cmd, capture_output=True, text=True)
        data = json.loads(result.stdout)
        return float(data['format']['duration'])
    except Exception as e:
        print(f"获取音频时长出错: {str(e)}")
        # 返回估计值 (每150个单词约100秒)
        return 100.0

def convert_to_audio(pdf_path):
    """
    将PDF内容转换为多个音频文件，每100秒一个文件
    
    Args:
        pdf_path: PDF文件路径
        
    Returns:
        list: 音频文件信息列表
    """
    # 确保音频文件目录存在
    audio_dir = 'audio_files'
    os.makedirs(audio_dir, exist_ok=True)
    
    # 从PDF提取文本
    with open(pdf_path, 'rb') as file:
        reader = PyPDF2.PdfReader(file)
        
        if not reader.pages:
            return []  # PDF没有页面
            
        # 提取每页文本
        text = ""
        for page in reader.pages:
            page_text = page.extract_text()
            if page_text:
                text += page_text
    
    if not text.strip():
        return []  # 提取的文本为空
    
    # 将文本分割成段落
    text_segments, all_words = text_to_segments(text)
    
    # 追踪文件列表
    audio_files = []
    
    # 追踪当前积累的文本 (为了控制音频长度)
    current_segment_parts = []
    current_word_count = 0
    current_audio_duration = 0
    segment_index = 0
    
    # 首词和尾词追踪
    segment_first_word = None
    segment_last_word = None
    
    # 处理每个文本片段
    for i, segment in enumerate(text_segments):
        print(f"处理文本段落 {i+1}/{len(text_segments)}...")
        
        # 提取当前段落中有意义的第一个和最后一个单词
        words = [w for w in word_tokenize(segment) if w.isalpha()]
        
        if not words:
            continue
            
        # 更新当前段落的第一个和最后一个单词
        if segment_first_word is None:
            segment_first_word = words[0]
        
        segment_last_word = words[-1]
        
        # 添加到当前累积段落
        current_segment_parts.append(segment)
        current_word_count += len(words)
        
        # 估计时长 (大约每150个单词100秒)
        estimated_duration = current_word_count / MAX_WORDS_PER_SEGMENT * 100
        
        # 检查是否达到最大持续时间
        if estimated_duration >= 100 or i == len(text_segments) - 1:
            # 合并当前段落并创建音频
            full_segment = " ".join(current_segment_parts)
            
            # 创建文件名
            filename = f"{get_segment_name(segment_first_word, segment_last_word)}.mp3"
            filepath = os.path.join(audio_dir, filename)
            
            try:
                # 将文本转换为音频
                tts = gTTS(full_segment, lang='en', slow=False)
                tts.save(filepath)
                
                # 获取文件时长
                duration = get_file_duration(filepath)
                
                # 添加到文件列表
                audio_files.append({
                    'file': filename,
                    'path': filepath,
                    'duration': duration,
                    'first_word': segment_first_word,
                    'last_word': segment_last_word,
                    'word_count': current_word_count
                })
                
                # 重置跟踪变量
                current_segment_parts = []
                current_word_count = 0
                segment_first_word = None
                segment_last_word = None
                segment_index += 1
                
            except Exception as e:
                print(f"处理文本段落时出错: {str(e)}")
                # 继续处理下一个段落
    
    return audio_files

def get_audio_files():
    """
    获取音频文件目录中的所有音频文件
    
    Returns:
        list: 音频文件信息列表
    """
    audio_dir = 'audio_files'
    audio_files = []
    
    if not os.path.exists(audio_dir):
        return audio_files
    
    for filename in os.listdir(audio_dir):
        if filename.endswith('.mp3'):
            filepath = os.path.join(audio_dir, filename)
            
            # 尝试解析文件名格式 first_word-last_word.mp3
            name_parts = os.path.splitext(filename)[0].split('-')
            if len(name_parts) >= 2:
                first_word = name_parts[0]
                last_word = name_parts[-1]
            else:
                first_word = "unknown"
                last_word = "unknown"
            
            # 获取文件大小
            file_size = os.path.getsize(filepath)
            
            # 获取文件时长
            duration = get_file_duration(filepath)
            
            audio_files.append({
                'file': filename,
                'path': filepath,
                'first_word': first_word,
                'last_word': last_word,
                'size': file_size,
                'duration': duration
            })
    
    # 按文件名排序
    audio_files.sort(key=lambda x: x['file'])
    
    return audio_files 